SMOODEV-2392: th config set derives tier from schema, secret for unknown (ADR-075 WS1)#180
Merged
Merged
Conversation
…own (ADR-075 WS1) `th config set` defaulted `--tier public` and never consulted the schema, so a secret mislabeled public failed silently (the 2026-07-08 incident: four live credentials stored tier=public). ADR-075 makes the schema authoritative. `th config set` now: - Derives the tier from the key's declaration across the org's schema union (public/secret/feature_flag/limit) when --tier is omitted; a key declared in no schema defaults to `secret` (the loud-failure direction) with a warning. - Refuses an explicit --tier that contradicts the schema tier (naming it); --force overrides, still warning. - Credential tripwire: a public-tier write of a credential-shaped value (sk-, github_pat_, ghp_, xox, -----BEGIN, long JWT) prompts on a TTY and refuses non-interactively unless --force. Server-side enforcement (Phase 1) lands separately; this is the D6 UX guardrail that ships with Phase 0. Pure derivation/contradiction/tripwire logic is unit tested (12 tests). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LE7V35vzRiHyxBFE8wAxb4
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
th config setdefaulted--tier publicand never consulted the schema. Tier is a real security boundary (secret-tier is AES-encrypted at rest, B2M keys can't read secret tier, the ADR-074 app surface serves public-tier to anonymous callers), and the failure is asymmetric: a public key mislabeled secret fails loud, a secret mislabeled public fails silent. The 2026-07-08 audit found four live credentials storedtier=public. ADR-075 makes the schema authoritative.Solution (ADR-075 WS1 / D6 — the CLI UX guardrail that ships with server Phase 0)
th config set:--tieris omitted, look the key up across the union of the org's remote schemas (public / secret / feature_flag / limit). Found → use the schema's tier. Declared in no schema → defaultsecret(the loud-failure direction) with a warning. Conflicting tiers across schemas →secretwins (D1 migration tiebreak).--tierthat contradicts the schema tier is refused with an error naming the schema tier;--forceoverrides (still warns).sk-,github_pat_,ghp_,xox,-----BEGIN, or a long three-part JWT) prompts for confirmation on a TTY and refuses non-interactively unless--force.--help/ module docs updated.Server-side derivation + 400-on-contradiction (Phase 1) lands separately in WS2/the TS routes; this is the D6 CLI layer that ships with Phase 0.
Verification
cargo test -p smooai-smooth-cli— 337 passed. 12 new unit tests cover tier derivation across all four schema kinds, the secret-wins union tiebreak, bare-doc tolerance, everyresolve_set_tierbranch (schema default, unknown→secret, matching/contradicting explicit ± force), the credential-shape heuristic (incident classes + benign negatives), and the tripwire decision (force/tty/non-tty). Derivation, contradiction, and tripwire logic are pure functions.rustfmt --checkclean; clippy shows only pre-existing workspace pedantic warnings.Warnings go to stderr so
--jsonstdout stays a clean wire shape.🤖 Generated with Claude Code
https://claude.ai/code/session_01LE7V35vzRiHyxBFE8wAxb4